package com.share.infrastructure.persistent.repository;

import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import com.alibaba.fastjson.JSON;
import com.share.domain.rebate.model.aggregate.BehaviorRebateAggregate;
import com.share.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import com.share.domain.rebate.model.entity.TaskEntity;
import com.share.domain.rebate.model.valobj.BehaviorTypeVo;
import com.share.domain.rebate.model.valobj.DailyBehaviorRebateVo;
import com.share.domain.rebate.repository.IBehaviorRebateRepository;
import com.share.infrastructure.event.EventPublisher;
import com.share.infrastructure.persistent.dao.IDailyBehaviorRebateDao;
import com.share.infrastructure.persistent.dao.ITaskDao;
import com.share.infrastructure.persistent.dao.IUserBehaviorRebateOrderDao;
import com.share.infrastructure.persistent.po.DailyBehaviorRebate;
import com.share.infrastructure.persistent.po.Task;
import com.share.infrastructure.persistent.po.UserBehaviorRebateOrder;
import com.share.types.enums.ResponseCode;
import com.share.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 行为返利仓储实现
 */
@Repository
@Slf4j
public class BehaviorRebateRepository implements IBehaviorRebateRepository {

    @Resource
    private IDailyBehaviorRebateDao dailyBehaviorRebateDao;
    @Resource
    private IUserBehaviorRebateOrderDao userBehaviorRebateOrderDao;
    @Resource
    private ITaskDao taskDao;
    @Resource
    private IDBRouterStrategy dbRouter;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private EventPublisher eventPublisher;

    @Override
    public List<DailyBehaviorRebateVo> queryDailyBehaviorRebateConfig(BehaviorTypeVo behaviorTypeVo) {
        List<DailyBehaviorRebate> dailyBehaviorRebateConfigList = dailyBehaviorRebateDao.queryDailyBehaviorRebateByBehaviorType(behaviorTypeVo.getCode());
        List<DailyBehaviorRebateVo> dailyBehaviorRebateVoList = new ArrayList<>();
        for (DailyBehaviorRebate dailyBehaviorRebate : dailyBehaviorRebateConfigList) {
            DailyBehaviorRebateVo dailyBehaviorRebateVo = DailyBehaviorRebateVo.builder()
                    .behaviorType(dailyBehaviorRebate.getBehaviorType())
                    .rebateDesc(dailyBehaviorRebate.getRebateDesc())
                    .rebateType(dailyBehaviorRebate.getRebateType())
                    .rebateConfig(dailyBehaviorRebate.getRebateConfig())
                    .build();
            dailyBehaviorRebateVoList.add(dailyBehaviorRebateVo);
        }
        return dailyBehaviorRebateVoList;
    }

    @Override
    public List<BehaviorRebateOrderEntity> queryOrderByOutBusinessNo(String userId, String outBusinessNo) {
        //数据库请求对象
        UserBehaviorRebateOrder userBehaviorRebateOrder = new UserBehaviorRebateOrder();
        userBehaviorRebateOrder.setOutBusinessNo(outBusinessNo);
        userBehaviorRebateOrder.setUserId(userId);

        List<UserBehaviorRebateOrder> userBehaviorRebateOrders = userBehaviorRebateOrderDao.queryOrderByOutBusinessNo(userBehaviorRebateOrder);
        List<BehaviorRebateOrderEntity> behaviorRebateOrderEntities = new ArrayList<>(userBehaviorRebateOrders.size());
        for (UserBehaviorRebateOrder behaviorRebateOrder : userBehaviorRebateOrders) {
            BehaviorRebateOrderEntity behaviorRebateOrderEntity = BehaviorRebateOrderEntity.builder()
                        .userId(behaviorRebateOrder.getUserId())
                        .orderId(behaviorRebateOrder.getOrderId())
                        .behaviorType(behaviorRebateOrder.getBehaviorType())
                        .rebateDesc(behaviorRebateOrder.getRebateDesc())
                        .rebateType(behaviorRebateOrder.getRebateType())
                        .rebateConfig(behaviorRebateOrder.getRebateConfig())
                        .outBusinessNo(behaviorRebateOrder.getOutBusinessNo())
                        .bizId(behaviorRebateOrder.getBizId())
                        .build();
            behaviorRebateOrderEntities.add(behaviorRebateOrderEntity);
        }
        return behaviorRebateOrderEntities;

    }

    @Override
    public void saveUserRebateRecord(String userId, List<BehaviorRebateAggregate> behaviorRebateAggregates) {
        try {
            dbRouter.doRouter(userId);
            transactionTemplate.execute(status -> {
                try {
                    for (BehaviorRebateAggregate behaviorRebateAggregate : behaviorRebateAggregates) {
                        BehaviorRebateOrderEntity behaviorRebateOrderEntity = behaviorRebateAggregate.getBehaviorRebateOrderEntity();

                        UserBehaviorRebateOrder userBehaviorRebateOrder = new UserBehaviorRebateOrder();
                        userBehaviorRebateOrder.setUserId(behaviorRebateOrderEntity.getUserId());
                        userBehaviorRebateOrder.setOrderId(behaviorRebateOrderEntity.getOrderId());
                        userBehaviorRebateOrder.setBehaviorType(behaviorRebateOrderEntity.getBehaviorType());
                        userBehaviorRebateOrder.setRebateDesc(behaviorRebateOrderEntity.getRebateDesc());
                        userBehaviorRebateOrder.setRebateType(behaviorRebateOrderEntity.getRebateType());
                        userBehaviorRebateOrder.setRebateConfig(behaviorRebateOrderEntity.getRebateConfig());
                        userBehaviorRebateOrder.setOutBusinessNo(behaviorRebateOrderEntity.getOutBusinessNo());
                        userBehaviorRebateOrder.setBizId(behaviorRebateOrderEntity.getBizId());

                        userBehaviorRebateOrderDao.insert(userBehaviorRebateOrder);

                        TaskEntity taskEntity = behaviorRebateAggregate.getTaskEntity();
                        Task task = new Task();
                        task.setUserId(taskEntity.getUserId());
                        task.setTopic(taskEntity.getTopic());
                        task.setMessageId(taskEntity.getMessageId());
                        task.setMessage(JSON.toJSONString(taskEntity.getMessage()));
                        task.setState(taskEntity.getState().getCode());
                        taskDao.insert(task);
                    }
                    return 1;
                }catch (DuplicateKeyException e){
                    status.setRollbackOnly();
                    log.info("【回滚】写入返利记录，唯一索引冲突 userId:{}",userId);
                    throw new AppException(ResponseCode.INDEX_DUP.getCode(),e);
                }
            });
        }finally {
            dbRouter.clear();
        }

        //同步发送mq消息
        for (BehaviorRebateAggregate behaviorRebateAggregate : behaviorRebateAggregates) {
            TaskEntity taskEntity = behaviorRebateAggregate.getTaskEntity();
            Task task = new Task();
            task.setMessageId(taskEntity.getMessageId());
            task.setUserId(taskEntity.getUserId());
            try {
                eventPublisher.publish(taskEntity.getTopic(), taskEntity.getMessage());
                taskDao.updateTaskSendMessageCompleted(task);
            }catch (Exception e){
                log.info("行为返利Mq消息发送失败userId:{},messageId:{}",task.getUserId(),task.getMessageId());
                taskDao.updateTaskSendMessageFail(task);
            }
        }
    }
}
